import os
import json
from datetime import datetime, timedelta
from collections import defaultdict, OrderedDict
from pyecharts import options as opts
from pyecharts.charts import Line
from pyecharts.globals import ThemeType
from pathlib import Path
import logging
import shutil
from logging.handlers import TimedRotatingFileHandler
import requests
import time
import json
import sys
import os
def clear_directory(dir_path):
    """
    清空指定目录的所有内容（保留目录本身）
    
    参数:
        dir_path (str): 要清空的目录路径
    """
    # 确保目录存在
    if not os.path.exists(dir_path):
        os.makedirs(dir_path)
        return
    
    # 验证路径是目录
    if not os.path.isdir(dir_path):
        raise ValueError(f"路径 '{dir_path}' 不是目录")
    
    # 遍历删除目录内容
    for item in os.listdir(dir_path):
        item_path = os.path.join(dir_path, item)
        
        try:
            if os.path.isfile(item_path) or os.path.islink(item_path):
                os.unlink(item_path)  # 删除文件或符号链接
            elif os.path.isdir(item_path):
                shutil.rmtree(item_path)  # 递归删除子目录
        except Exception as e:
            print(f"删除 {item_path} 失败: {str(e)}")
            # 可根据需要添加错误处理逻辑

def setup_logging(
        name: str = "app",
        log_dir: str = "logs",
        level: str = "INFO",
        when: str = "D",
        backup_count: int = 7,
        fmt: str = "%(asctime)s - %(levelname)s - %(module)s:%(lineno)d - %(message)s"
) -> logging.Logger:
    """
    初始化日志配置

    参数：
        name (str): 日志名称/应用名称，默认 'app'
        log_dir (str): 日志存储目录，默认 'logs'
        level (str): 日志级别（DEBUG/INFO/WARNING/ERROR/CRITICAL），默认 'INFO'
        when (str): 日志轮换间隔单位，默认 'D'（天），可选值：
                    'S' 秒, 'M' 分, 'H' 小时, 'D' 天, 'W0'-'W6' 周
        backup_count (int): 保留的旧日志文件数量，默认7
        fmt (str): 日志格式，默认包含时间、级别、模块、行号和消息

    返回：
        logging.Logger: 配置好的Logger对象

    示例：
        >>> logger = setup_logging()
        >>> logger.info("系统启动")
    """
    try:
        # 创建日志目录
        os.makedirs(log_dir, exist_ok=True)

        # 初始化日志对象
        logger = logging.getLogger(name)
        logger.setLevel(level)

        # 清除已有处理器避免重复
        if logger.handlers:
            for handler in logger.handlers[:]:
                logger.removeHandler(handler)

        # 设置日志格式
        formatter = logging.Formatter(fmt=fmt, datefmt="%Y-%m-%d %H:%M:%S")

        # 文件处理器（按时间轮换）
        file_handler = TimedRotatingFileHandler(
            filename=os.path.join(log_dir, f"{name}.log"),
            when=when,
            backupCount=backup_count,
            encoding="utf-8"
        )
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

        # 控制台处理器
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(formatter)
        logger.addHandler(console_handler)

        return logger

    except PermissionError as e:
        sys.stderr.write(f"日志文件写入权限不足: {str(e)}\n")
        raise
    except Exception as e:
        sys.stderr.write(f"日志初始化失败: {str(e)}\n")
        raise

# 计算总页数
def calculate_total_pages(total_records, count_per_page):
    return (total_records + count_per_page - 1) // count_per_page


#获取请求头
def get_headers(cookie_value):
    return  {
    "Accept": "application/json, text/plain, */*",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "zh-CN,zh;q=0.9",
    "Connection": "keep-alive",
    "Cookie": cookie_value,
    "Host": ips,
    "Referer": f"{hosts}/member/history",
    "sec-ch-ua": '"Chromium";v="104", " Not A;Brand";v="99", "Google Chrome";v="104"',
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": '"Windows"',
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
}


def merge_json_files(input_dir, output_file):
    # 初始化一个空列表，用于存储所有的 items
    all_items = []
    path = Path(output_file)
    if path.exists():
        try:
            path.unlink()  # 删除文件
        except Exception as e: 
            logger.error(f"删除文件时出错: {e}")
    else:
        logger.info(f"文件 {output_file} 不存在")

    # 遍历输入目录中的所有文件
    for filename in os.listdir(input_dir):
        if filename.endswith('.json'):
            file_path = os.path.join(input_dir, filename)

            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)

                    # 提取 items 数组并添加到 all_items 列表中
                    items = data.get("items", [])
                    all_items.extend(items)

                print(f"Processed {filename}")

            except json.JSONDecodeError as e:
                print(f"Error decoding JSON in {filename}: {e}")
            except Exception as e:
                print(f"Error processing {filename}: {e}")

    # 将所有 items 合并成一个新的 JSON 文件
    output_data = {
        "items": all_items
    }

    with open(output_file, 'w', encoding='utf-8') as f:
        json.dump(output_data, f, ensure_ascii=False, indent=4)

    return output_file

def read_and_sort_data(file_path: str) -> list:
    """
    读取并预处理彩票数据

    参数：
        file_path: JSON文件路径

    返回：
        按时间排序后的数据列表

    异常：
        FileNotFoundError: 文件不存在时抛出
        ValueError: JSON解析失败时抛出
    """
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
    except FileNotFoundError:
        raise FileNotFoundError(f"数据文件 {file_path} 未找到")
    except json.JSONDecodeError:
        raise ValueError("JSON文件解析失败，请检查格式")

    return sorted(data['items'], key=lambda x: x['open_time'])



# 发送GET请求并保存结果
def fetch_and_save_data(cookie_value, total_records, count_per_page, lottery_id,save_dir,TARGET_NUMBERS,BET_CONFIG):
    global next_spider_date
    # 计算总页数
    total_pages = calculate_total_pages(total_records, count_per_page)
    print(f"Total pages to fetch: {total_pages}")
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)
    output_filename = f"merged_{datetime.now().strftime('%Y%m%d')}.json"
    output_file = os.path.join(save_dir, output_filename)
    # 循环请求每一页的数据
    for page in range(0, total_pages + 1):
        url = f"{hosts}/api/mem/lottery/history/{lottery_id}?count={count_per_page}&page={page}&lottery_id={lottery_id}"
        headers = get_headers(cookie_value)

        try:
            response = requests.get(url, headers=headers)

            # 检查响应状态码
            if response.status_code == 200:
                data = response.json()

                # 打印返回的结果
                print(f"Fetched page {page}/{total_pages}")

                # 生成文件名
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                filename = f"{save_dir}/{timestamp}_lottery_id_{lottery_id}.json"

                # 保存数据到文件
                with open(filename, 'w', encoding='utf-8') as f:
                    json.dump(data, f, ensure_ascii=False, indent=4)

                print(f"Saved data to {filename}")
            else:
                print(f"Request failed with status code: {response.status_code}")
                print(f"Response: {response.text}")

            # 每次请求后休息2秒
            if page < total_pages:
                time.sleep(3)
        except requests.exceptions.RequestException as e:
            print(f"Request error on page {page}: {e}")
    #合并数据
    merge_json_files(save_dir, output_file)
    # 定义最新一期的开奖时间，便于下次爬取数据的时间
    sorted_items = read_and_sort_data(output_file)
    current_date = sorted_items[-1]["open_time"]
    # 下次爬取数据的时间
    original_date = datetime.strptime(current_date, "%Y-%m-%d %H:%M:%S")
    # 添加 1分25秒
    delta = timedelta(minutes=1, seconds=27)
    next_spider_date = original_date + delta

    calc(output_file,save_dir,TARGET_NUMBERS,BET_CONFIG)



def group_data_by_date(data):
    """按日期分组数据并按期号升序排列"""
    daily_data = defaultdict(list)
    for item in data['items']:
        open_time = datetime.strptime(item['open_time'], "%Y-%m-%d %H:%M:%S")
        daily_data[open_time.date()].append(item)

    # 对每天的数据按期号升序排列
    for date in daily_data:
        daily_data[date] = sorted(daily_data[date], key=lambda x: int(x['issue_no']))

    return daily_data


def analyze_lottery(data, target_numbers,bet_config):
    """分析彩票数据，按上一期关键号码位置在当前期对应位置下注"""
    daily_data = group_data_by_date(data)
    daily_results = {}

    # 全局累计数据
    global_cumulative_issues = 0
    global_cumulative_wins = 0

    # 按日期排序
    sorted_dates = sorted(daily_data.keys())

    for date in sorted_dates:
        items = daily_data[date]
        date_str = date.strftime("%Y-%m-%d")
        print(f"分析日期: {date_str}，共 {len(items)} 期数据")

        daily_result = {
            'date': date_str,
            'total_issues': len(items),
            'win_count': 0,
            'bet_config': bet_config,
            'counter_data': [],
            'consecutive_bet_data': []  # 连续押注数据
        }

        # 当天累计数据
        daily_cumulative_issues = 0
        daily_cumulative_wins = 0

        # 从第二期开始分析（因为第一期没有上一期数据）
        for i in range(1, len(items)):
            current_issue = items[i]
            current_issue_no = current_issue['issue_no']
            current_open_code = current_issue['open_code']
            current_open_time = current_issue['open_time']
            current_codes = current_open_code.split(',')

            # 获取上一期数据
            prev_issue = items[i - 1]
            prev_issue_no = prev_issue['issue_no']
            prev_open_code = prev_issue['open_code']
            prev_codes = prev_open_code.split(',')

            # 提取上一期关键号码的位置（位置从1开始）
            positions_target = [pos + 1 for pos, code in enumerate(prev_codes) if code in target_numbers]

            # 计算当前期的中奖情况
            win_count = 0
            win_positions = []
            win_codes = []

            # 在当前期的相同位置检查是否中奖
            for pos in positions_target:
                if 0 <= pos - 1 < len(current_codes):
                    current_code = current_codes[pos - 1]
                    if current_code in bet_config[target_numbers[0]]:  # 使用第一个目标号码的配置
                        win_count += 1
                        win_positions.append(pos)
                        win_codes.append(current_code)

            # 更新全局累计数据
            global_cumulative_issues += 1
            global_cumulative_wins += win_count

            # 更新当天的累计数据
            daily_cumulative_issues += 1
            daily_cumulative_wins += win_count

            # 记录计数器数据，使用全局累计数据
            counter = global_cumulative_issues / jsq1 - global_cumulative_wins

            daily_result['counter_data'].append({
                'issue_no': current_issue_no,
                'daily_cumulative_issues': daily_cumulative_issues,
                'daily_cumulative_wins': daily_cumulative_wins,
                'global_cumulative_issues': global_cumulative_issues,
                'global_cumulative_wins': global_cumulative_wins,
                'counter': counter,
                'open_time': current_open_time,
                'win_count': win_count  # 新增，记录当期中奖数
            })

            # 更新总中奖数
            daily_result['win_count'] += win_count

            # 连续押注统计
            current_streak = 1 if win_count > 0 else 0
            if daily_result['consecutive_bet_data']:
                last_bet = daily_result['consecutive_bet_data'][-1]
                current_streak = last_bet['current_streak'] + 1 if win_count > 0 else 0

            max_streak = max(
                [bet['current_streak'] for bet in daily_result['consecutive_bet_data']] +
                [current_streak]
            ) if daily_result['consecutive_bet_data'] else current_streak

            daily_result['consecutive_bet_data'].append({
                'prev_issue_no': prev_issue_no,
                'current_issue_no': current_issue_no,
                'prev_open_code': prev_open_code,
                'bet_positions': positions_target,
                'current_open_code': current_open_code,
                'win_count': win_count,
                'win_positions': win_positions,
                'win_codes': win_codes,
                'current_streak': current_streak,
                'max_streak': max_streak,
                'open_time': current_open_time,
                'global_cumulative_issues': global_cumulative_issues,
                'global_cumulative_wins': global_cumulative_wins,
                'counter': counter
            })

        # 保存最终统计数据
        daily_result['max_streak'] = max([bet['max_streak'] for bet in daily_result['consecutive_bet_data']]) if \
            daily_result['consecutive_bet_data'] else 0

        daily_results[date] = daily_result

    return daily_results


def generate_counter_chart(counter_data, output_dir, date_str):
    """生成计数器折线图，包含开奖时间（优化tooltip显示）"""
    if not counter_data:
        return None

    sorted_counter_data = sorted(
        counter_data,
        key=lambda x: int(x['issue_no'])
    )

    issue_nos = [item['issue_no'] for item in sorted_counter_data]
    counters = [item['counter'] for item in sorted_counter_data]
    open_times = [item['open_time'] for item in sorted_counter_data]  # 提取开奖时间

    # 准备tooltip所需的完整数据
    tooltip_data = [
        f"期号: {item['issue_no']}<br/>开奖时间: {item['open_time']}<br/>计数器: {item['counter']:.2f}<br/>"
        f"全局累计期数: {item['global_cumulative_issues']}<br/>全局累计中奖数: {item['global_cumulative_wins']}"
        for item in sorted_counter_data
    ]

    line = (
        Line(init_opts=opts.InitOpts(
            theme=ThemeType.LIGHT,
            width="1000px",
            height="500px"
        ))
        .add_xaxis(issue_nos)
        .add_yaxis(
            "计数器",
            counters,
            is_smooth=True,
            label_opts=opts.LabelOpts(is_show=False),
            itemstyle_opts=opts.ItemStyleOpts(color="#3398DB")
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title=f"{date_str} 计数器变化趋势"),
            xaxis_opts=opts.AxisOpts(
                name="期号",
                type_="category",
                axislabel_opts=opts.LabelOpts(
                    rotate=60,
                    interval="auto",
                    font_size=10
                )
            ),
            yaxis_opts=opts.AxisOpts(
                name="计数器值",
                splitline_opts=opts.SplitLineOpts(is_show=True),
                axislabel_opts=opts.LabelOpts(formatter="{value}")
            ),
            toolbox_opts=opts.ToolboxOpts(is_show=True),
            tooltip_opts=opts.TooltipOpts(
                trigger="axis",
                axis_pointer_type="cross",
                formatter=lambda params: tooltip_data[params[0].data_index]
            ),
            datazoom_opts=[opts.DataZoomOpts()],
        )
    )

    chart_file = os.path.join(output_dir, f"counter_chart_{date_str}.html")
    line.render(chart_file)
    return chart_file


def generate_weekly_chart(weekly_data, output_dir, week_start, week_end):
    """生成每周的计数器折线图（修正：每周独立累计）"""
    if not weekly_data:
        return None

    # 准备数据并计算每周独立的累计期数和中奖数
    all_counter_data = []
    week_cumulative_issues = 0
    week_cumulative_wins = 0

    # 按日期排序
    sorted_dates = sorted(weekly_data.keys())

    for date in sorted_dates:
        day_data = weekly_data[date]
        date_str = date.strftime("%Y-%m-%d")
        if 'counter_data' in day_data and day_data['counter_data']:
            # 为每天的数据添加日期标识，并计算周累计数据
            for item in day_data['counter_data']:
                week_cumulative_issues += 1
                week_cumulative_wins += item['win_count']  # 使用当期中奖数

                # 计算周计数器（独立累计）
                week_counter = week_cumulative_issues / jsq1 - week_cumulative_wins

                # 复制并添加周数据
                new_item = item.copy()
                new_item['date'] = date_str
                new_item['week_cumulative_issues'] = week_cumulative_issues
                new_item['week_cumulative_wins'] = week_cumulative_wins
                new_item['week_counter'] = week_counter
                all_counter_data.append(new_item)

    if not all_counter_data:
        return None

    # 按期号排序
    all_counter_data.sort(key=lambda x: int(x['issue_no']))

    # 准备图表数据
    x_data = [f"{item['date']} {item['issue_no']}" for item in all_counter_data]
    y_data = [item['week_counter'] for item in all_counter_data]
    tooltip_data = [
        f"日期: {item['date']}<br/>期号: {item['issue_no']}<br/>开奖时间: {item['open_time']}<br/>"
        f"周计数器: {item['week_counter']:.2f}<br/>"
        f"周累计期数: {item['week_cumulative_issues']}<br/>周累计中奖数: {item['week_cumulative_wins']}<br/>"
        f"全局累计期数: {item['global_cumulative_issues']}<br/>全局累计中奖数: {item['global_cumulative_wins']}"
        for item in all_counter_data
    ]

    # 创建折线图
    line = (
        Line(init_opts=opts.InitOpts(
            theme=ThemeType.LIGHT,
            width="1000px",
            height="500px"
        ))
        .add_xaxis(x_data)
        .add_yaxis(
            "周计数器",
            y_data,
            is_smooth=True,
            label_opts=opts.LabelOpts(is_show=False),
            itemstyle_opts=opts.ItemStyleOpts(color="#3398DB")
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(
                title=f"{week_start.strftime('%Y-%m-%d')}~{week_end.strftime('%Y-%m-%d')} 周计数器变化趋势"),
            xaxis_opts=opts.AxisOpts(
                name="日期和期号",
                type_="category",
                axislabel_opts=opts.LabelOpts(
                    rotate=60,
                    interval="auto",
                    font_size=10
                )
            ),
            yaxis_opts=opts.AxisOpts(
                name="周计数器值",
                splitline_opts=opts.SplitLineOpts(is_show=True),
                axislabel_opts=opts.LabelOpts(formatter="{value}")
            ),
            toolbox_opts=opts.ToolboxOpts(is_show=True),
            tooltip_opts=opts.TooltipOpts(
                trigger="axis",
                axis_pointer_type="cross",
                formatter=lambda params: tooltip_data[params[0].data_index]
            ),
            datazoom_opts=[opts.DataZoomOpts()],
        )
    )

    chart_file = os.path.join(output_dir, f"weekly_counter_chart_{week_start.strftime('%Y%m%d')}.html")
    line.render(chart_file)
    return chart_file


def generate_monthly_chart(monthly_data, output_dir, year, month):
    """生成每月的计数器折线图（修正：每月独立累计）"""
    if not monthly_data:
        return None

    # 准备数据并计算每月独立的累计期数和中奖数
    all_counter_data = []
    month_cumulative_issues = 0
    month_cumulative_wins = 0

    # 按日期排序
    sorted_dates = sorted(monthly_data.keys())

    for date in sorted_dates:
        day_data = monthly_data[date]
        date_str = date.strftime("%Y-%m-%d")
        if 'counter_data' in day_data and day_data['counter_data']:
            # 为每天的数据添加日期标识，并计算月累计数据
            for item in day_data['counter_data']:
                month_cumulative_issues += 1
                month_cumulative_wins += item['win_count']  # 使用当期中奖数

                # 计算月计数器（独立累计）
                month_counter = month_cumulative_issues / jsq1 - month_cumulative_wins

                # 复制并添加月数据
                new_item = item.copy()
                new_item['date'] = date_str
                new_item['month_cumulative_issues'] = month_cumulative_issues
                new_item['month_cumulative_wins'] = month_cumulative_wins
                new_item['month_counter'] = month_counter
                all_counter_data.append(new_item)

    if not all_counter_data:
        return None

    # 按期号排序
    all_counter_data.sort(key=lambda x: int(x['issue_no']))

    # 准备图表数据
    x_data = [f"{item['date']} {item['issue_no']}" for item in all_counter_data]
    y_data = [item['month_counter'] for item in all_counter_data]
    tooltip_data = [
        f"日期: {item['date']}<br/>期号: {item['issue_no']}<br/>开奖时间: {item['open_time']}<br/>"
        f"月计数器: {item['month_counter']:.2f}<br/>"
        f"月累计期数: {item['month_cumulative_issues']}<br/>月累计中奖数: {item['month_cumulative_wins']}<br/>"
        f"全局累计期数: {item['global_cumulative_issues']}<br/>全局累计中奖数: {item['global_cumulative_wins']}"
        for item in all_counter_data
    ]

    # 创建折线图
    line = (
        Line(init_opts=opts.InitOpts(
            theme=ThemeType.LIGHT,
            width="1000px",
            height="500px"
        ))
        .add_xaxis(x_data)
        .add_yaxis(
            "月计数器",
            y_data,
            is_smooth=True,
            label_opts=opts.LabelOpts(is_show=False),
            itemstyle_opts=opts.ItemStyleOpts(color="#3398DB")
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title=f"{year}年{month}月 月计数器变化趋势"),
            xaxis_opts=opts.AxisOpts(
                name="日期和期号",
                type_="category",
                axislabel_opts=opts.LabelOpts(
                    rotate=60,
                    interval="auto",
                    font_size=10
                )
            ),
            yaxis_opts=opts.AxisOpts(
                name="月计数器值",
                splitline_opts=opts.SplitLineOpts(is_show=True),
                axislabel_opts=opts.LabelOpts(formatter="{value}")
            ),
            toolbox_opts=opts.ToolboxOpts(is_show=True),
            tooltip_opts=opts.TooltipOpts(
                trigger="axis",
                axis_pointer_type="cross",
                formatter=lambda params: tooltip_data[params[0].data_index]
            ),
            datazoom_opts=[opts.DataZoomOpts()],
        )
    )

    chart_file = os.path.join(output_dir, f"monthly_counter_chart_{year}{month}.html")
    line.render(chart_file)
    return chart_file


def generate_html_report(daily_result, data, output_dir,TARGET_NUMBERS,BET_CONFIG):
    """生成每天的HTML报告"""
    date_str = daily_result['date']
    output_file = os.path.join(output_dir, f"lottery_analysis_{date_str}.html")

    # 计算基本统计数据
    total_issues = daily_result['total_issues'] - 1  # 下注次数是总期数-1（第一天没有上一期）
    total_wins = daily_result['win_count']
    win_rate = f"{(total_wins / total_issues * 100) if total_issues > 0 else 0:.2f}%"

    config_display = ", ".join([f"{code}→{','.join(codes)}" for code, codes in daily_result['bet_config'].items()])

    # 生成计数器图表
    counter_chart = generate_counter_chart(daily_result['counter_data'], output_dir, date_str)

    # 连续押注统计
    consecutive_data = daily_result['consecutive_bet_data']
    has_consecutive_data = len(consecutive_data) > 0

    # 计算连续押注统计数据
    max_streak = daily_result['max_streak'] if has_consecutive_data else 0

    # 修复iframe部分的格式化问题
    if counter_chart and os.path.exists(counter_chart):
        chart_iframe = f'<iframe src="{os.path.basename(counter_chart)}" width="100%" height="550" frameborder="0"></iframe>'
    else:
        chart_iframe = '<div>无数据生成图表</div>'

    # 生成连续押注表格HTML
    bet_table_html = ""
    for bet in consecutive_data:
        bet_positions = ", ".join(map(str, bet['bet_positions'])) if bet['bet_positions'] else "无下注"
        win_positions = ", ".join(map(str, bet['win_positions'])) if bet['win_positions'] else "无中奖"
        win_codes = ", ".join(bet['win_codes']) if bet['win_codes'] else ""
        row_class = ' class="win"' if bet['win_count'] > 0 else ''

        bet_table_html += f"""
            <tr{row_class}>
                <td>{bet['prev_issue_no']}</td>
                <td>{bet['prev_open_code']}</td>
                <td>{bet_positions}</td>
                <td>{bet['current_issue_no']}</td>
                <td>{bet['current_open_code']}</td>
                <td>{win_positions}</td>
                <td>{win_codes}</td>
                <td>{bet['win_count']}</td>
                <td>{bet['current_streak']}</td>
                <td>{bet['global_cumulative_issues']}</td>
                <td>{bet['global_cumulative_wins']}</td>
                <td style="font-weight: bold;">{bet['counter']:.2f}</td>
                <td>{bet['open_time']}</td> <!-- 显示开奖时间 -->
            </tr>
        """

    # 构建完整的HTML内容
    html_content = f"""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{date_str} 彩票下注分析报告</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; }}
        h1 {{ color: #333; text-align: center; }}
        .stats-box {{ background-color: #f0f0f0; padding: 15px; border-radius: 5px; margin-bottom: 20px; }}
        .config-box {{ background-color: #e6f7ff; padding: 15px; border-radius: 5px; margin-bottom: 20px; }}
        .chart-box {{ margin: 30px 0; padding: 15px; border-radius: 5px; background-color: #f8f9fa; }}
        .stats-item {{ margin: 5px 0; }}
        .table-container {{ overflow-x: auto; margin: 30px 0; }}
        table {{ width: 100%; border-collapse: collapse; }}
        th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
        th {{ background-color: #e6e6e6; font-weight: bold; }}
        tr:nth-child(even) {{ background-color: #f9f9f9; }}
        .win {{ background-color: #d4edda; }}
        .nav {{ margin-bottom: 20px; text-align: center; }}
        .nav a {{ margin: 0 10px; }}
    </style>
</head>
<body>
    <div class="nav">
        <a href="index.html">返回总览</a>
        <a href="summary.html">查看汇总报告</a>
    </div>
    <h1>{date_str} 彩票下注分析报告</h1>

    <div class="config-box">
        <h3>下注规则配置</h3>
        <div class="stats-item">规则: {config_display}</div>
    </div>

    <div class="stats-box">
        <h3>当日统计数据</h3>
        <div class="stats-item">总期数: {daily_result['total_issues']}</div>
        <div class="stats-item">下注次数: {total_issues}</div>
        <div class="stats-item">中奖总次数: {total_wins}</div>
        <div class="stats-item">整体中奖率: {win_rate}</div>
    </div>

    <div class="chart-box">
        <h3>计数器变化趋势</h3>
        <p>计数器 = 全局累计期数 / {jsq1} - 全局累计中奖个数</p>
        <p>每天从第二期开始押注，累计期数连续计算</p>
        {chart_iframe}
    </div>

    <div class="table-container">
        <h3>每日连续押注中奖情况</h3>
        <p>根据上一期开{','.join(TARGET_NUMBERS)}的位置，在当前期相同位置押注{','.join(TARGET_NUMBERS)}</p>
        <div class="stats-item">最大连胜次数: {max_streak} 次</div>

        <table>
            <tr>
                <th>上一期期号</th>
                <th>上一期开奖号码</th>
                <th>下注位置</th>
                <th>当前期期号</th>
                <th>当前期开奖号码</th>
                <th>中奖位置</th>
                <th>中奖号码</th>
                <th>中奖个数</th>
                <th>当前连胜次数</th>
                <th>全局累计期数</th>
                <th>全局累计中奖数</th>
                <th>计数器</th>
                <th>开奖时间</th> <!-- 新增开奖时间列 -->
            </tr>
            {bet_table_html}
        </table>
    </div>
</body>
</html>
    """

    with open(output_file, 'w', encoding='utf-8') as f:
        f.write(html_content)
    return output_file


def generate_summary_html(daily_results, output_dir):
    """生成汇总HTML报告（修正：每周和每月独立累计）"""
    output_file = os.path.join(output_dir, "summary.html")

    # 提取每日最后一期的计数器值
    daily_last_counters = {}
    for date, result in daily_results.items():
        date_str = date.strftime("%Y-%m-%d")
        if result['counter_data']:
            # 获取当天最后一期的计数器值
            last_counter = result['counter_data'][-1]['counter']
            global_issues = result['counter_data'][-1]['global_cumulative_issues']
            global_wins = result['counter_data'][-1]['global_cumulative_wins']
            daily_last_counters[date] = {
                'date_str': date_str,
                'last_counter': last_counter,
                'global_issues': global_issues,
                'global_wins': global_wins,
                'link': f"lottery_analysis_{date_str}.html",
                'counter_data': result['counter_data']  # 保存完整的计数器数据
            }

    # 按周分组数据（按日期升序排列）
    sorted_dates = sorted(daily_last_counters.keys())  # 改为升序排列
    weekly_data = {}

    if sorted_dates:
        # 从最早日期开始，按周分组
        current_week_start = sorted_dates[0]

        for date in sorted_dates:
            # 计算与当前周开始日期的差值
            delta = (date - current_week_start).days

            # 如果差值大于等于7天，开始新的一周
            if delta >= 7:
                current_week_start = date

            # 将日期添加到对应的周
            if current_week_start not in weekly_data:
                weekly_data[current_week_start] = {}

            weekly_data[current_week_start][date] = daily_last_counters[date]

    # 按月分组数据（按日期升序排列）
    monthly_data = {}

    for date in sorted_dates:
        year_month = f"{date.year}-{date.month}"

        if year_month not in monthly_data:
            monthly_data[year_month] = {}

        monthly_data[year_month][date] = daily_last_counters[date]

    # 生成每周的折线图
    weekly_charts = []
    for week_start, week_data in weekly_data.items():
        # 计算周结束日期
        dates_in_week = sorted(week_data.keys())
        week_end = dates_in_week[-1]

        chart_file = generate_weekly_chart(
            {date: daily_results[date] for date in week_data.keys()},
            output_dir,
            week_start,
            week_end
        )
        if chart_file:
            # 计算周累计数据（独立计算）
            week_total_issues = 0
            week_total_wins = 0

            for date in dates_in_week:
                day_data = daily_results[date]
                if 'counter_data' in day_data and day_data['counter_data']:
                    # 计算当天的下注次数（总期数-1）
                    day_bets = len(day_data['counter_data'])
                    week_total_issues += day_bets

                    # 计算当天的总中奖数
                    day_wins = sum(item['win_count'] for item in day_data['counter_data'])
                    week_total_wins += day_wins

            weekly_charts.append({
                'start': week_start,
                'end': week_end,
                'chart_file': chart_file,
                'days': list(week_data.values()),
                'total_issues': week_total_issues,
                'total_wins': week_total_wins
            })

    # 生成每月的折线图
    monthly_charts = []
    for year_month, month_data in monthly_data.items():
        year, month = year_month.split('-')
        # 计算月结束日期
        dates_in_month = sorted(month_data.keys())
        month_end = dates_in_month[-1]

        chart_file = generate_monthly_chart(
            {date: daily_results[date] for date in month_data.keys()},
            output_dir,
            year,
            month
        )
        if chart_file:
            # 计算月累计数据（独立计算）
            month_total_issues = 0
            month_total_wins = 0

            for date in dates_in_month:
                day_data = daily_results[date]
                if 'counter_data' in day_data and day_data['counter_data']:
                    # 计算当天的下注次数（总期数-1）
                    day_bets = len(day_data['counter_data'])
                    month_total_issues += day_bets

                    # 计算当天的总中奖数
                    day_wins = sum(item['win_count'] for item in day_data['counter_data'])
                    month_total_wins += day_wins

            monthly_charts.append({
                'year': year,
                'month': month,
                'chart_file': chart_file,
                'days': list(month_data.values()),
                'total_issues': month_total_issues,
                'total_wins': month_total_wins
            })

    # 生成周图表HTML
    weekly_charts_html = ""
    for week in weekly_charts:
        week_start_str = week['start'].strftime("%Y-%m-%d")
        week_end_str = week['end'].strftime("%Y-%m-%d")
        week_win_rate = f"{(week['total_wins'] / week['total_issues'] * 100):.2f}%" if week[
                                                                                           'total_issues'] > 0 else "0.00%"

        # 生成周内每天的计数器值表格
        week_days_html = ""
        for day in sorted(week['days'], key=lambda x: x['date_str']):  # 按日期排序
            day_class = "up" if day['last_counter'] >= 28 else ("down" if day['last_counter'] <= 22 else "neutral")
            week_days_html += f"""
                <tr>
                    <td><a href="{day['link']}">{day['date_str']}</a></td>
                    <td class="{day_class}">{day['last_counter']:.2f}</td>
                    <td>{day['global_issues']}</td>
                    <td>{day['global_wins']}</td>
                </tr>
            """

        weekly_charts_html += f"""
            <div class="chart-item">
                <h3>{week_start_str}~{week_end_str} 周计数器变化趋势</h3>
                <div class="stats-item">周累计期数: {week['total_issues']}</div>
                <div class="stats-item">周累计中奖数: {week['total_wins']}</div>
                <div class="stats-item">周中奖率: {week_win_rate}</div>
                <iframe src="{os.path.basename(week['chart_file'])}" width="100%" height="500" frameborder="0"></iframe>

                <div class="table-container">
                    <table>
                        <tr>
                            <th>日期</th>
                            <th>当日最后一期计数器值</th>
                            <th>全局累计期数</th>
                            <th>全局累计中奖数</th>
                        </tr>
                        {week_days_html}
                    </table>
                </div>
            </div>
        """

    # 生成月图表HTML
    monthly_charts_html = ""
    for month in monthly_charts:
        month_win_rate = f"{(month['total_wins'] / month['total_issues'] * 100):.2f}%" if month[
                                                                                              'total_issues'] > 0 else "0.00%"

        # 生成月内每天的计数器值表格
        month_days_html = ""
        for day in sorted(month['days'], key=lambda x: x['date_str']):  # 按日期排序
            day_class = "up" if day['last_counter'] >= 28 else ("down" if day['last_counter'] <= 22 else "neutral")
            month_days_html += f"""
                <tr>
                    <td><a href="{day['link']}">{day['date_str']}</a></td>
                    <td class="{day_class}">{day['last_counter']:.2f}</td>
                    <td>{day['global_issues']}</td>
                    <td>{day['global_wins']}</td>
                </tr>
            """

        monthly_charts_html += f"""
            <div class="chart-item">
                <h3>{month['year']}年{month['month']}月 月计数器变化趋势</h3>
                <div class="stats-item">月累计期数: {month['total_issues']}</div>
                <div class="stats-item">月累计中奖数: {month['total_wins']}</div>
                <div class="stats-item">月中奖率: {month_win_rate}</div>
                <iframe src="{os.path.basename(month['chart_file'])}" width="100%" height="500" frameborder="0"></iframe>

                <div class="table-container">
                    <table>
                        <tr>
                            <th>日期</th>
                            <th>当日最后一期计数器值</th>
                            <th>全局累计期数</th>
                            <th>全局累计中奖数</th>
                        </tr>
                        {month_days_html}
                    </table>
                </div>
            </div>
        """

    # 构建完整的HTML内容
    html_content = f"""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>彩票下注分析汇总报告</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; }}
        h1 {{ color: #333; text-align: center; }}
        .chart-box {{ margin: 30px 0; padding: 15px; border-radius: 5px; background-color: #f8f9fa; }}
        .table-container {{ overflow-x: auto; margin: 30px 0; }}
        table {{ width: 100%; border-collapse: collapse; }}
        th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
        th {{ background-color: #e6e6e6; font-weight: bold; }}
        tr:nth-child(even) {{ background-color: #f9f9f9; }}
        .nav {{ margin-bottom: 20px; text-align: center; }}
        .nav a {{ margin: 0 10px; }}
        .up {{ color: #ff4d4f; }}
        .down {{ color: #52c41a; }}
        .neutral {{ color: #333; }}
        .module {{ margin: 30px 0; padding: 20px; border: 1px solid #ddd; border-radius: 5px; }}
        .module h2 {{ margin-top: 0; }}
        .chart-item {{ margin-bottom: 50px; }}
    </style>
</head>
<body>
    <div class="nav">
        <a href="index.html">返回总览</a>
    </div>
    <h1>彩票下注分析汇总报告</h1>

    <div class="module">
        <h2>模块1：周计数器变化趋势（每周单独图表）</h2>
        <p>周计数器 = 周累计期数 / {jsq1} - 周累计中奖个数</p>
        {weekly_charts_html}
    </div>

    <div class="module">
        <h2>模块2：月计数器变化趋势（每月单独图表）</h2>
        <p>月计数器 = 月累计期数 / {jsq1} - 月累计中奖个数</p>
        {monthly_charts_html}
    </div>
</body>
</html>
    """

    with open(output_file, 'w', encoding='utf-8') as f:
        f.write(html_content)
    return output_file


def generate_index_html(dates, output_dir):
    """生成索引页面"""
    output_file = os.path.join(output_dir, "index.html")
    html_content = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>彩票下注分析报告总览</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        h1 { color: #333; text-align: center; }
        .date-list { max-width: 800px; margin: 0 auto; }
        .date-item { margin: 10px 0; padding: 10px; background-color: #f0f0f0; border-radius: 5px; }
        .date-item a { text-decoration: none; color: #0066cc; }
        .date-item a:hover { text-decoration: underline; }
        .nav { margin-bottom: 20px; text-align: center; }
        .nav a { margin: 0 10px; }
    </style>
</head>
<body>
    <div class="nav">
        <a href="summary.html">查看汇总报告</a>
    </div>
    <h1>彩票下注分析报告总览</h1>

    <div class="date-list">
    """

    for date in sorted(dates):  # 按日期升序排列
        date_str = date.strftime("%Y-%m-%d")
        html_content += f"""
        <div class="date-item">
            <a href="lottery_analysis_{date_str}.html">{date_str}</a>
        </div>
        """

    html_content += """
    </div>
</body>
</html>
    """

    with open(output_file, 'w', encoding='utf-8') as f:
        f.write(html_content)
    return output_file


def spiderWeekCharData(cookie_value,lottery_id,ip,host,choose_number,jsq):
    try:
        global ips,hosts,next_spider_date,logger,fetch_data,logger,jsq1
        logger = setup_logging(
        name="mychar",
        log_dir="./runtime/logs",
        level="DEBUG")
        next_spider_date = None
        # 1. 按逗号分割成键值对列表
        pairs = choose_number.split(',')
        BET_CONFIG = {}
        for pair in pairs:
            key, value = pair.split(':')
            BET_CONFIG[key] = [value]  # 值包装成列表
        TARGET_NUMBERS = list(BET_CONFIG.keys())
        jsq1 = float(jsq)
        ips = ip
        hosts = host
        fetch_data = False
        total_records = 9000
        count_per_page1 = 50
        lottery_id = 16
        current_date_1 = datetime.now().strftime('%Y%m%d')
        save_dir = f"spider_char_data_week_{current_date_1}"
        clear_directory(save_dir)
        count_per_page = 2  # 每页记录数
        page = 0

        if next_spider_date == None:
            fetch_and_save_data(cookie_value, total_records, count_per_page1, lottery_id,save_dir,TARGET_NUMBERS,BET_CONFIG)
    except Exception as e:
        logger.error(f"hu - {str(e)}")
        return False
    
def calc(json_file,save_dir,TARGET_NUMBERS,BET_CONFIG):
    """主函数"""
    output_dir = f"{save_dir}//lottery_reports//car"
    os.makedirs(output_dir, exist_ok=True)

    try:
        with open(json_file, 'r', encoding='utf-8') as f:
            data = json.load(f)
        
           # 过滤出当天数据
        filtered_items = [
        item for item in data.get('items', [])]
        seen_issues = {}
        unique_items = []
        # 先按open_time降序排序，确保每个issue_no只保留最新的一条
        for item in sorted(filtered_items, key=lambda x: x.get('open_time', ''), reverse=True):
            issue_no = item.get('issue_no')
            if issue_no and issue_no not in seen_issues:
                seen_issues[issue_no] = True
                unique_items.append(item)
        data = {"items": sorted(unique_items, key=lambda x: x.get('open_time', ''))}
        daily_results = analyze_lottery(data,TARGET_NUMBERS,BET_CONFIG)
        if not daily_results:
            print("警告: 没有找到有效的数据进行分析")
            return


        print("正在生成汇总报告...")
        summary_file = generate_summary_html(daily_results, output_dir)
        print(f"已生成汇总报告: {summary_file}")

        index_file = generate_index_html(daily_results.keys(), output_dir)
        print(f"已生成索引页面: {index_file}")

    except Exception as e:
        print(f"处理过程中出错: {e}")


if __name__ == "__main__":
    cookie = "visid_incap_2980419=egSo2iMFQliCP0i77FKHaPjjRmgAAAAAQUIPAAAAAACa4YBjddlB0TgVo4QAkZgU; incap_ses_893_2980419=LUitCRj1aw8GGr32DJNkDLxZfmgAAAAAlwvss9M9rBCIqArtDuDmRg==; koa:sess=f192037bc78d9842c73b8f8ad58c9884269a97933325a369; nlbi_2980419=umq8IhGoC2BwlPk2hHMyXgAAAAD4E5Fz9+yeS4x/DbY8s6iO"
    spiderWeekCharData(cookie,16,"c181532.sys998.com","https://c181532.sys998.com","01:01,02:02,03:03,04:04","2.5")